const parse = require('@babel/parser').parse
const generator = require('@babel/generator').default;
const traverse = require('@babel/traverse').default;
const types = require('@babel/types')
const fs = require('fs')
const path = require('path');

// 自行将后面讲的三个特征的代码放到这

// 待反混淆的文件
let jsCode = fs.readFileSync(path.resolve(__dirname, 'encode.js'), { encoding: 'utf-8' });

let ast = parse(jsCode);

let list = [];
const generateRandomString = () =>
    Array.from({ length: 3 }, () =>
        'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'[Math.floor(Math.random() * 52)]
    ).join('');

function getRandomName() {
    let name = generateRandomString();
    while (true) {
        if (list.indexOf(name) === -1) {
            list.push(name);
            break;
        } else {
            name = generateRandomString();
        }
    }
    return name;
}

traverse(ast, {
    // 捕捉函数调用打印
    FunctionDeclaration: {
        exit(path) {
            let name = path.node.id.name;
            let line = path.node.loc.start.line;
            let obj = types.memberExpression(object = types.identifier("console"), property = types.identifier("log"))
            let call = types.callExpression(callee = obj, _arguments = [types.stringLiteral("name:"),
            types.stringLiteral(name), types.stringLiteral("line:"), types.numericLiteral(Number(line))])
            let expre = types.expressionStatement(expression = call)
            path.node.body.body.unshift(expre);
        }
    },
    // 捕捉异常打印
    CatchClause: {
        exit(path) {
            let { node } = path;
            if (types.isIdentifier(node.param)) {
                let name = node.param.name;
                let obj = types.memberExpression(object = types.identifier("console"), property = types.identifier("log"))
                let call = types.callExpression(callee = obj, _arguments = [types.identifier(name)])
                let expre = types.expressionStatement(expression = call)
                node.body.body.unshift(expre)
            }
        }
    },
    // 随机变量名
    VariableDeclarator: {
        exit(path) {
            let { node, scope } = path;
            let binding = scope.getBinding(node.id.name);
            if (!binding) {
                return;
            }
            for (const referencePath of binding.referencePaths) {
                scope.rename(referencePath.node.name, getRandomName());
            }
        }
    }
})

//将上面的代码重新解析成 AST，更新 loc 中的行号值
ast = parse(generator(ast, opts = {
    "compact": false,
    "comments": false,
    "jsescOption": { "minimal": true },
}).code)

traverse(ast, {
    FunctionDeclaration: {
        exit(path) {
            let { node } = path;
            let line = node.loc.start.line;//获取行号
            node.body.body[0].expression.arguments[3].value = line;//更新行号
        }
    }
})



// 语法数转JS代码
let { code } = generator(ast, { compact: false });

// 保存
fs.writeFile(path.resolve(__dirname, './decode.js'), code, (err) => {
});